#pragma once

#include "HkpRigidBodyCinfo.h"
#include "..\..\..\Common\HkIncludes.h"
#include "..\..\Collision\Agent\HkpCollidable.h"

class hkStatisticsCollector;
class hkClass;

using namespace Microsoft::Xna::Framework;

namespace Havok
{
	namespace Dynamics
	{
		/// <remarks>
		/// This is the basic rigid body class. Rigid bodies are objects whose shape never changes.
		/// They are central to Havok dynamics, as they easily allow for rapid physical simulation
		/// in real time.
		/// </remarks>
		public ref class HkpRigidBody
		{
		public:

			HkpRigidBody(hkpRigidBody* native)
			{
				m_native = native;
			}

			///<summary>
			/// The constructor takes the information from the passed info parameter.
			///</summary>
			///<param name="info">This contains all the information necessary to create a valid rigid body.</param>
			HkpRigidBody(HkpRigidBodyCinfo^ info);

			///<summary>
			///</summary>
			property Matrix Transform
			{
			public:
				virtual Matrix get();
			};
			
			///<summary>
			/// Gets of sets rotation of rigid body.
			///</summary>
			property Quaternion Rotation
			{
			public:
				virtual void set(Quaternion value);
				virtual Quaternion get();
			}
			
			///<summary>
			/// Gets of sets position of rigid body.
			///</summary>
			property Vector3 Position
			{
			public:
				virtual void set(Vector3 value);
				virtual Vector3 get();
			}
			
			///<summary>
			/// Gets or sets mass of the rigid body. Default = 1
			///</summary>
			property float Mass
			{
			public:
				virtual void set(float value);
				virtual float get();
			}
			
			///<summary>
			/// Gets of sets Center of Mass in local space of the rigid body. Default = 0,0,0
			///</summary>
			property Vector3 CenterOfMassLocal
			{
			public:
				virtual void set(Vector3 value);
				virtual Vector3 get();
			}
			
			///<summary>
			/// Gets of sets Center of Mass in world space of the rigid body.
			///</summary>
			property Vector3 CenterOfMassWorld
			{
			public:
				virtual Vector3 get();
			}
			
			///<summary>
			/// Gets or sets linear velocity of rigid body at center of mass.
			///</summary>
			property Vector3 LinearVelocity
			{
			public:
				virtual void set(Vector3 value);
				virtual Vector3 get();
			}
			
			///<summary>
			/// Gets or sets angular velocity of rigid body at center of mass.
			///</summary>
			property Vector3 AngularVelocity
			{
			public:
				virtual void set(Vector3 value);
				virtual Vector3 get();
			}
			
			///<summary>
			/// Gets or sets linear damping of rigid body. Default = 0
			///</summary>
			property float LinearDamping
			{
			public:
				virtual void set(float value);
				virtual float get();
			}
			
			///<summary>
			/// Gets or sets angular damping of rigid body. Default = 0.05
			///</summary>
			property float AngularDamping
			{
			public:
				virtual void set(float value);
				virtual float get();
			}
			
			///<summary>
			/// Gets or sets maximal velocity of rigid body. Default = 200
			///</summary>			
			property float MaxLinearVelocity
			{
			public:
				virtual void set(float value);
				virtual float get();
			}
			
			///<summary>
			/// Gets or sets maximal velocity of rigid body. 
			/// The units used here are half revolutions per sec rather than the usual radians per second. Defaut = 200.
			///</summary>
			property float MaxAngularVelocity
			{
			public:
				virtual void set(float value);
				virtual float get();
			}
			
			///<summary>
			///</summary>
			//property float AllowedPenetrationDepth
			//{
			//public:
			//	virtual void set(float value);
			//	virtual float get();
			//}


			///<summary>
			/// Gets or sets friction of rigid body when coliding.
			///</summary>
			property float Friction
			{
			public:
				virtual void set(float value);
				virtual float get();
			}
			
			///<summary>
			/// Gets or sets restitution of rigid body when coliding.
			///</summary>
			property float Restitution
			{
			public:
				virtual void set(float value);
				virtual float get();
			}
			
			///<summary>
			/// Applies linear impulse to center of mass of rigid body.
			///</summary>
			void ApplyLinearImpulse(Vector3 impulse);

			///<summary>
			/// Applies linear impulse to specified point on rigid body.
			///</summary>
			void ApplyPointImpulse(Vector3 impulse, Vector3 point);

			///<summary>
			/// Applies angular impulse to rigid body.
			///</summary>
			void ApplyAngularImpulse(Vector3 impulse);

			///<summary>
			/// Applies force to center of mass of rigid body.
			///</summary>
			void ApplyForce(GameTime^ gameTime, Vector3 force);

			///<summary>
			/// Applies torque to rigid boty.
			///</summary>
			void ApplyTorque(GameTime^ gameTime, Vector3 torque);
			
			hkpRigidBody* m_native;

			static HkpRigidBody^ GetRigidBody(Collision::HkpCollidable^ collidable);
		};
	}
}
